package com.hbnu.service.impl;

import com.hbnu.domain.LoginTourist;
import com.hbnu.service.impl.AsyncEmailService;
import com.hbnu.tourist.domain.Tourist;
import com.hbnu.service.LoginService;
import com.hbnu.tourist.mapper.TouristMapper;
import com.hbnu.util.EmailUtil;
import com.hbnu.util.Jwt;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class LoginServiceImpl implements LoginService {
    // 认证管理器
    @Autowired
    @Qualifier("touristAuthenticationManager")
    private AuthenticationManager touristAuthenticationManager;
    //redis
    @Autowired
    private RedisCache redisCache;
    // 邮箱发送工具
    @Autowired
    private EmailUtil emailUtil;
    // 数据层
    @Autowired
    private TouristMapper touristMapper;
    // 密码加密
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AsyncEmailService asyncEmailService;
    @Override
    public AjaxResult login(Tourist tourist) {
        try {
            UsernamePasswordAuthenticationToken token =
                    new UsernamePasswordAuthenticationToken(tourist.getEmail(), tourist.getPassword());

            Authentication authenticate = touristAuthenticationManager.authenticate(token);
            LoginTourist loginTourist = (LoginTourist) authenticate.getPrincipal();

            // 生成JWT和缓存逻辑
            String jwt = Jwt.createJwt(loginTourist.getTourist().getId(), tourist.getEmail());
            redisCache.setCacheObject("login:" + loginTourist.getTourist().getId(), loginTourist.getTourist(), 7, TimeUnit.DAYS);

            return AjaxResult.success("登录成功")
                    .put("code",200)
                    .put("id", loginTourist.getTourist().getId())
                    .put("token", jwt)
                    .put("name", loginTourist.getTourist().getName());
        } catch (AuthenticationException e) {
            return AjaxResult.error(402, e.getMessage());
        }
    }

    @Override
    public AjaxResult register(Tourist tourist,String code) {
        String newCode = redisCache.getCacheObject("code:" + tourist.getEmail());
        if (newCode == null){
            return AjaxResult.error(402, "验证码已过期");
        }
        Tourist user = touristMapper.selectTouristByEmail(tourist.getEmail());
        if (user != null&& user.getStatus() == 0) {
            log.info("用户已存在");
            return AjaxResult.error(402, "用户名已存在");
        }
        if (user != null&& user.getStatus() == 1) {
            log.info("用户恢复以前账号");
            user.setPassword(passwordEncoder.encode(tourist.getPassword()));
            user.setUpdateTime(DateUtils.getNowDate());
            user.setStatus(0L);
            int i = touristMapper.updateTourist(user);
            if (i == 1) {
                String jwt = Jwt.createJwt(user.getId(), user.getEmail());
                redisCache.setCacheObject("login:" + user.getId(), user, 7, TimeUnit.DAYS);
                return AjaxResult.success("登录以前账号成功")
                        .put("code",200)
                        .put("token", jwt)
                        .put("name", user.getName());
            }
            return AjaxResult.error(402,"恢复以前账号失败，一个手机号只能有一个账号");
        }
        tourist.setName(tourist.getEmail());
        tourist.setCreateTime(DateUtils.getNowDate());
        tourist.setStatus(0L);
        tourist.setPassword(passwordEncoder.encode(tourist.getPassword()));
        int i = touristMapper.insertTourist(tourist);
        if (i == 1) {
            Tourist touristMain = touristMapper.selectTouristByEmail(tourist.getEmail());

            String jwt = Jwt.createJwt(touristMain.getId(), touristMain.getEmail());
            redisCache.setCacheObject("login:" + touristMain.getId(), touristMain, 7, TimeUnit.DAYS);

            return AjaxResult.success("注册成功")
                    .put("code",200)
                    .put("token", jwt)
                    .put("name", touristMain.getName());
        }
        return AjaxResult.error(402, "注册失败");
    }

    @Override
    public AjaxResult updatePassword(Tourist tourist,String code) {
        String newCode = redisCache.getCacheObject("code:" + tourist.getEmail());
        if (newCode == null){
            return AjaxResult.error(402, "验证码已过期");
        }
        Tourist touristMain = touristMapper.selectTouristByEmail(tourist.getEmail());
        if (touristMain != null) {
            touristMain.setPassword(passwordEncoder.encode(tourist.getPassword()));
            touristMain.setUpdateTime(DateUtils.getNowDate());
            int i = touristMapper.updateTourist(touristMain);
            if (i == 1) {
                return AjaxResult.success("修改密码成功")
                        .put("code",200);
            }
            return AjaxResult.error(402, "修改密码失败");
        }
        return AjaxResult.error(402, "用户不存在");
    }
    @Override
    public AjaxResult getCode(String email, String text) {
        String code = emailUtil.getCode();
        log.info("邮箱验证码：{}", code);
        asyncEmailService.sendCodeAsync(email, text, code);
        log.info("已经在异步发送", code);
        redisCache.setCacheObject("code:"+email, code, 5, TimeUnit.MINUTES);
        return AjaxResult.success("发送成功")
                .put("code",200);
    }

    @Override
    public AjaxResult findPassword(String email, String text) {
        String newCode = redisCache.getCacheObject("code:" + email);
        if (newCode.equals(text)){
            return AjaxResult.success( "验证成功")
                    .put("code",200);
        }
        return AjaxResult.error(402, "验证码错误");
    }

}
